package product.jbpmDesign;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.imageio.ImageIO;

import net.sf.json.JSONObject;

import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.DualHashBidiMap;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;

import snippets.xml.Dom4jUtil;
/**
 *������:
 *@���� hjl
 *@����:2012-10-8 ʱ��:����03:23:45
 *@����:�ṩ���õ�ͳһ������
 */
public class JbpmDesignService {
	private Dom4jUtil dom4jUtil = new Dom4jUtil(); 
	private BidiMap rectIdToNameMap = new DualHashBidiMap();
	//�õ�xml��Ӧjson,��Ҫ�ı���
	private JSONObject restoreJson = new JSONObject();
	private JSONObject statesJson = new JSONObject();
	private JSONObject pathsJson = new JSONObject();
	private JSONObject propsJson = new JSONObject();
	
	private void buildStatesJson(Document document,String[] paths){
		int rectNo=1;
		for(String path:paths){
			String xPath="//xmlns:"+path;
			List<Node> nodeList = dom4jUtil.getNodes(document, xPath);
			for(Node node:nodeList){
				if(node!=null){
					JSONObject jsonObject = new JSONObject();
					//����
					String rectId = "rect"+(rectNo++);
					if(StringUtils.isNotEmpty(node.valueOf("@g"))){
						RectPosition nodePosition = new RectPosition();
						nodePosition.doSplit(node.valueOf("@g"));
						jsonObject.put("attr",nodePosition);
					}
					if(StringUtils.isNotEmpty(node.getName())){
						jsonObject.put("type", node.getName());
					}
					if(StringUtils.isNotEmpty(node.valueOf("@name"))){
						jsonObject.put("text",new JSONObject().element("text",node.valueOf("@name")));
						jsonObject.put("props",new JSONObject().element("text",new JSONObject().element("value",node.valueOf("@name"))));
					}
					//taskӵ��
					if(StringUtils.isNotEmpty(node.valueOf("@assignee"))){
						jsonObject.put("assignee",node.valueOf("@assignee"));
					}
					if(StringUtils.isNotEmpty(node.valueOf("@form"))){
						jsonObject.put("form",node.valueOf("@form"));
					}
					if(StringUtils.isNotEmpty(node.valueOf("@expr"))){
						jsonObject.put("expr",node.valueOf("@expr"));
					}
					//jionӵ��
					if(StringUtils.isNotEmpty(node.valueOf("@multiplicity"))){
						jsonObject.put("multiplicity",node.valueOf("@multiplicity"));
					}
					//foreachӵ��
					if(StringUtils.isNotEmpty(node.valueOf("@in"))){
						jsonObject.put("in",node.valueOf("@in"));
					}
					if(StringUtils.isNotEmpty(node.valueOf("@var"))){
						jsonObject.put("var",node.valueOf("@var"));
					}
					rectIdToNameMap.put(rectId,node.valueOf("@name"));
					statesJson.put(rectId,jsonObject);
				}				
			}		
		}		
	}
	
	private void buildPathsJson(Document document){
		int pathNo=1;
		String xPath="//xmlns:transition";
		List<Element> transitionList = dom4jUtil.getNodes(document, xPath);
		for(Element element:transitionList){
			if(element!=null){
				JSONObject jsonObject = new JSONObject();
				Element parentElement = element.getParent();
				String rectFromId = (String)rectIdToNameMap.getKey(parentElement.attribute("name").getValue());
				jsonObject.put("from",rectFromId);
				if(element.attribute("to")!=null){
					String rectToId = (String)rectIdToNameMap.getKey(element.attribute("to").getValue());
					jsonObject.put("to",rectToId);
				}
				if(element.attribute("name")!=null){
					jsonObject.put("text",new JSONObject().element("text",element.attribute("name").getValue()));
				}else{
					jsonObject.put("text",new JSONObject().element("text",""));
				}
				if(element.attribute("g")!=null){
					LinePosition linePosition = new LinePosition();
					linePosition.doSplit(element.attribute("g").getValue());
					//jsonObject.put("g",linePosition);
					jsonObject.put("dots",linePosition.getDotsList());
					if(StringUtils.isNotBlank(linePosition.getTextPos().toString())){
						jsonObject.put("textPos",linePosition.getTextPos());
					}
					//jsonObject.put("g",linePosition);
				}else{
					jsonObject.put("dots","[]");
				}
				pathsJson.put("path"+(pathNo++),jsonObject);
			}
		}	
	}
	
	private void bulidPropsJson(Document document){
		String xPath="//xmlns:process";
		Node process = dom4jUtil.getSingleNode(document, xPath);
		if(process!=null){
			JSONObject jsonObject = new JSONObject();
			if(StringUtils.isNotEmpty(process.valueOf("@key"))){
				jsonObject.put("key",new JSONObject().element("value",process.valueOf("@key")));
			}
			if(StringUtils.isNotEmpty(process.valueOf("@name"))){
				jsonObject.put("name",new JSONObject().element("value",process.valueOf("@name")));
			}
			propsJson.put("props",jsonObject);
		}		
	}
	
	public JSONObject getJSONObjectFromObjectData(File file){
		Document document = dom4jUtil.getDocument(file);
		String[] paths = {"start","task","decision","join","foreach","end"};
		buildStatesJson(document, paths);
		buildPathsJson(document);
		bulidPropsJson(document);
		restoreJson.put("states",statesJson);
		restoreJson.put("paths",pathsJson);
		restoreJson.put("props",propsJson);
		return restoreJson;
	}
	
	public void saveXml(File xmlFile,String xml){
		xml = dom4jUtil.formatXmlStr(xml);
		try {
			FileUtils.writeStringToFile(xmlFile,xml,"utf-8");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void buildPngFromXml(File xmlFile,File pngFile){
		try {
			InputStream is = new FileInputStream(xmlFile);    
			JpdlModel jpdlModel = new JpdlModel (is);        
			ImageIO.write(new JpdlModelDrawer().draw(jpdlModel), "png",pngFile);   } 
			catch (FileNotFoundException e) {        
				e.printStackTrace();   
			} 
			catch (IOException e) {
				e.printStackTrace();   
			} catch (Exception e) {   
				e.printStackTrace();   
			}		
	}
	
	private void out(Object object){
		System.out.println(object);
	}
	public JSONObject getStatesJson() {
		return statesJson;
	}

	public void setStatesJson(JSONObject statesJson) {
		this.statesJson = statesJson;
	}

	public JSONObject getPathsJson() {
		return pathsJson;
	}

	public void setPathsJson(JSONObject pathsJson) {
		this.pathsJson = pathsJson;
	}

	public JSONObject getPropsJson() {
		return propsJson;
	}

	public void setPropsJson(JSONObject propsJson) {
		this.propsJson = propsJson;
	}

	public JSONObject getRestoreJson() {
		return restoreJson;
	}

	public void setRestoreJson(JSONObject restoreJson) {
		this.restoreJson = restoreJson;
	}
	
}
